package br.com.obardavez.util.impl;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import br.com.obardavez.util.Util;
import br.com.obardavez.util.XmlUtil;

import com.google.inject.Inject;

public class XmlUtilImpl implements XmlUtil {

	private static final long serialVersionUID = 1L;

	@Inject
	private Util util;

	@Override
	public String format(Document doc) {

		DOMSource domSource = new DOMSource(doc);
		StringWriter writer = new StringWriter();
		StreamResult result = new StreamResult(writer);
		TransformerFactory tf = TransformerFactory.newInstance();

		try {

			Transformer transformer = tf.newTransformer();
			transformer.transform(domSource, result);

		} catch (TransformerException e) {
			e.printStackTrace();
			throw new RuntimeException("Error reading xml text.", e);
		}

		return writer.toString();
	}

	@Override
	public Document readFile(File file) {

		DocumentBuilderFactory docFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder docBuilder;

		try {

			docBuilder = docFactory.newDocumentBuilder();
			Document doc = docBuilder.parse(file);
			return doc;
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			throw new RuntimeException("Error parsing file.");
		} catch (SAXException e) {
			e.printStackTrace();
			throw new RuntimeException("Error reading file.");
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("Error reading file.");
		}

	}

	@Override
	public Document readInputStream(InputStream is) {

		DocumentBuilderFactory docFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder docBuilder;

		try {

			docBuilder = docFactory.newDocumentBuilder();
			Document doc = docBuilder.parse(is);
			return doc;

		} catch (ParserConfigurationException e) {
			e.printStackTrace();
			throw new RuntimeException("Error parsing file.");
		} catch (SAXException e) {
			e.printStackTrace();
			throw new RuntimeException("Error reading file.");
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("Error reading file.");
		}

	}

	public Util getUtil() {
		return util;
	}

	public void setUtil(Util util) {
		this.util = util;
	}

	@Override
	public String readChildNodeValue(Node node, String childNodeName) {

		String value = "";

		if (node != null && node.hasChildNodes()) {
			for (int i = 0; i < node.getChildNodes().getLength(); i++) {
				Node childNode = node.getChildNodes().item(i);
				if (childNode.getNodeName().toUpperCase()
						.equals(childNodeName.toUpperCase())) {

					value = childNode.getNodeValue();
					if(util.getStringUtil().isEmpty(value)){
						value = childNode.getTextContent();
					}
					break;
				}
			}
		}

		return value;
	}

	@Override
	public Node findChildNodeByName(Node parentNode, String childNodeName) {

		Node child = null;

		if (parentNode != null && parentNode.hasChildNodes()) {
			for (int i = 0; i < parentNode.getChildNodes().getLength(); i++) {
				Node childNode = parentNode.getChildNodes().item(i);
				if (childNode.getNodeName().toUpperCase()
						.equals(childNodeName.toUpperCase())) {

					child = childNode;
					break;
				}
			}
		}

		return child;
	}

	@Override
	public List<Node> findChildNodesByName(Node parentNode, String childNodeName) {

		List<Node> children = new ArrayList<Node>();

		if (parentNode != null && parentNode.hasChildNodes()) {
			for (int i = 0; i < parentNode.getChildNodes().getLength(); i++) {
				Node childNode = parentNode.getChildNodes().item(i);
				if (childNode.getNodeName().toUpperCase()
						.equals(childNodeName.toUpperCase())) {

					children.add(childNode);
				}
			}
		}

		return children;
	}
}
